<template>
  <div :class="[prefixCls+'-all']">
    <div :class="[prefixCls+'-frame']" v-if="searchForm">
      <div :class="[prefixCls+'-title',prefixCls+'-title-top']" v-if="config.title">
        <span>{{config.title}}</span>
      </div>
      <div :class="[prefixCls+'-search']">
        <div :class="[prefixCls+'-simple-search']">
          <el-form :inline="true" :model="formParam" :class="prefixCls + '-form-inline'" ref="searchFormRef" label-width="120px">
            <el-form-item v-for="(item, index) in searchForm" :key="index" :label="item.label" :prop="item.key" :class="[prefixCls+'-search-item']"
              v-if="prefixCls !=='grid' || (prefixCls==='grid' && index < 3)">
              <el-input v-if="item.type === 'input'" v-model="formParam[item.key]"></el-input>
              <el-date-picker v-if="item.type === 'date'" v-model="formParam[item.key]" value-format="yyyy-MM-dd"></el-date-picker>
              <el-select v-if="item.type === 'select'" v-model="formParam[item.key]" style="width: 202px" :disabled=item.isDisabled>
                <el-option v-for="(d,i) in tempDict[item.key]" :key="i" :label="d.label" :value="d.value"></el-option>
              </el-select>
              <el-select v-if="item.type === 'multipleSelect'" multiple v-model="formParam[item.key]">
                <el-option v-for="(d,i) in tempDict[item.key]" :key="i" :label="d.label" :value="d.value"></el-option>
              </el-select>
              <select-tree v-if="item.type === 'select-tree'" :code.sync="formParam[item.key]" :multiple="false"></select-tree>
            </el-form-item>
            <div v-if="moreShow">
              <el-form-item v-for="(item, index) in searchForm" :key="index" :label="item.label" :prop="item.key" :class="[prefixCls+'-search-item']"
                v-if="prefixCls==='grid' && index >= 3">
                <el-input v-if="item.type === 'input'" v-model="formParam[item.key]"></el-input>
                <el-date-picker v-if="item.type === 'date'" v-model="formParam[item.key]" value-format="yyyy-MM-dd"></el-date-picker>
                <el-select v-if="item.type === 'select'" v-model="formParam[item.key]">
                  <el-option v-for="(d,i) in tempDict[item.key]" :key="i" :label="d.label" :value="d.value"></el-option>
                </el-select>
                <el-select v-if="item.type === 'multipleSelect'" multiple v-model="formParam[item.key]">
                  <el-option v-for="(d,i) in tempDict[item.key]" :key="i" :label="d.label" :value="d.value"></el-option>
                </el-select>
                <select-tree v-if="item.type === 'select-tree'" :code.sync="formParam[item.key]" :multiple="false"></select-tree>
              </el-form-item>
            </div>
            <div class="clearfix">
              <el-form-item class="fr" :class="[prefixCls+'-search-item']">
                <el-button type="success" icon="el-icon-search" @click="search">查询</el-button>
                <el-button type="info" icon="el-icon-refresh" @click="resetForm()">重置</el-button>
                <el-button type="primary" icon="el-icon-d-caret" v-if="prefixCls==='grid' && searchForm.length > 3" @click="moreShow = !moreShow">更多</el-button>
                <slot name="form-action"></slot>
              </el-form-item>
            </div>
          </el-form>
        </div>
      </div>
    </div>
    <div :class="[prefixCls+'-frame']">
      <div :class="[prefixCls+'-title table-title']" v-if="config.title">
        <span>{{config.title}}列表</span>
        <div :class="[prefixCls+'-table-action']">
          <slot name="table-action"></slot>
          <el-button type="info" icon="el-icon-delete" v-if="config.crudMapping.delete" @click="deleteSelect()" style="margin-left: 16px">{{config.crudMapping.delete.text? config.crudMapping.delete.text: '删除'}}</el-button>
          <el-button type="success" icon="el-icon-success" v-if="config.crudMapping.publish" @click="publishSelect()" style="margin-left: 16px">发布</el-button>
        </div>
      </div>
      <div :class="[prefixCls+'-table-tip']">
        <slot name="table-tip"></slot>
      </div>
      <div :class="[prefixCls+'-table']">
        <el-table :data="tableData" stripe min-height="250" max-height="640" border style="width: 100%" :height="config.tableHeight" ref="commonTable" @selection-change="handleSelectionChange"
          @sort-change="sortChange" @row-dblclick="dbClickAction" :header-cell-class-name="prefixCls+'-table-header-cell'"
          :cell-class-name="prefixCls+'-table-cell'" :highlight-current-row="config.currentRow" @current-change="currentChange">

          <el-table-column fixed type="selection" align="center" width="50" v-if="config.crudMapping.delete || config.selection"></el-table-column>
          <el-table-column fixed label="序号" align="center" width="60" v-if="config.isNo">
            <template slot-scope="scope">
              {{scope.$index + pageSize*(pageNo-1) + 1}}
            </template>
          </el-table-column>
          <el-table-column :show-overflow-tooltip="true" v-for="(item, index) in columns" v-if="!item.render && !item.hidden" :key="index" :prop="item.key" :label="item.label"
            :sortable="item.order?'custom':false" :width="item.width" :fixed="item.fixed?item.fixed:false" :align="item.align?item.align: config.align?config.align: 'left'">
          </el-table-column>
          <el-table-column :show-overflow-tooltip="true" :label="item.label" :fixed="item.fixed?item.fixed:false" v-else-if="!item.hidden" :width="item.width" :sortable="item.order?'custom':false" :align="item.align?item.align: config.align?config.align: 'left'">
            <template slot-scope="scope">
              <table-cell :row="scope.row" :render="item.render" :index="scope.$index"></table-cell>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <div :class="[prefixCls+'-page']" v-if="config.isPage">
        <el-pagination :current-page="pageNo" :page-sizes="[10, 50, 100]" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper"
          :total="total" @current-change="pageChange" @size-change="sizeChange">
        </el-pagination>
      </div>
    </div>
  </div>
</template>
<script>
  import TableCell from './table-cell'; //动态渲染用js
  import SelectTree from '../select-ext/select-tree';
  export default {
    data() {
      return {
        tableData: [], //列表数据
        formParam: {}, //查询表单
        searchParam: {}, //查询用数据，与查询表单结构一样。由于翻页时，即使查询数据变更也不会用新的数据查询，这里深拷贝一份
        pageNo: 1, //页码
        pageSize: 10, //显示行数
        total: 0, //总数据条数
        multipleSelection: [], //当前选中行数据
        checkedId: '', //是否有选中行
        moreShow: false,
        tempOrder: '',
        prefixCls: 'grid',
        tempDict: {},
        tableCurrentRow: null
      }
    },
    props: ['columns', 'searchForm', 'config'],
    methods: {
      searchInit() { //查询表单初始化,将数组=>Object用于数据双向绑定
        this.searchForm.forEach((item) => {
          this.$set(this.formParam, item.key, '');
          if (item.dict && item.dict instanceof Array) {
            this.$set(this.tempDict, item.key, item.dict)
          } else if (item.dict && item.dict.url) {

            let arrayParam = item.dict.url.match(new RegExp('(\\w+?)(?=})', 'g'));
            if (arrayParam && arrayParam.length > 0) {
              for (let i = 0; i < arrayParam.length; i++) {
                let _this = this;
                this.$watch('formParam.' + arrayParam[i], function (val) {
                  let url = item.dict.url.replace('{' + arrayParam[i] + '}', val);
                  let method = item.dict.method ? item.dict.method : 'post';
                  _this.formParam[item.key] = '';
                  _this.axios[method](url).then((res) => {
                    let array = res.data.map((d) => {
                      return {
                        label: d[item.dict.label],
                        value: d[item.dict.value]
                      }
                    });
                    _this.$set(this.tempDict, item.key, array);
                  });
                });
              }
            } else {
              let method = item.dict.method ? item.dict.method : 'post';
              this.axios[method](item.dict.url).then((res) => {
                let array = res.data.map((d) => {
                  return {
                    label: d[item.dict.label],
                    value: d[item.dict.value]
                  }
                });
                this.$set(this.tempDict, item.key, array);
              });

            }
          }
        });
      },
      currentChange(now, old){
        this.tableCurrentRow = now;
      },
      getCurrentRow(){
        return this.tableCurrentRow;
      },
      resetForm() { //重置
        this.$refs['searchFormRef'].resetFields();
        Object.keys(this.config.crudMapping.query.data).forEach(k => { // 避免默认查询参数不被清空
          this.formParam[k] = this.config.crudMapping.query.data[k] + '';
        })
      },
      getTableData() {
        return this.tableData;
      },
      search() { //查询
        //编辑查询用参数
        this.editParam(this.formParam);
        this.refreshTable();
      },
      refreshTable() {
        this.tableData = [];
        this.pageNo = 1;
        this.searchPost();
      },
      searchPost() { //查询请求
        // this.$notify({
        //   title: '查询参数',
        //   message: JSON.stringify(this.searchParam),
        //   type: 'success'
        // });
        let data = {};
        if (this.searchForm) {
          data = Object.assign({}, this.searchParam, {
            pageNo: this.config.isPage ? this.pageNo : 0,
            pageSize: this.config.isPage ? this.pageSize : 0
          });
        }
        if (this.config.crudMapping.query.data) {
          data = Object.assign({}, data, this.config.crudMapping.query.data);
          Object.keys(this.config.crudMapping.query.data).forEach(k => {
            this.formParam[k] = this.config.crudMapping.query.data[k] + '';
          })
        }
        this.axios.post(this.config.crudMapping.query.url, data).then((response) => {
          if (this.config.crudMapping.query.resultFun && typeof this.config.crudMapping.query.resultFun ===
            'function') {
            let result = this.config.crudMapping.query.resultFun(response);
            if (result && result.list)
              this.tableData = result.list;
            if (result && result.total)
              this.total = result.total;
          } else {
            console.log(33)
            console.log(response.data.rows)
            this.tableData = response.data.rows;
            this.total = response.data.total;
          }
          if (this.checkedId != '' && this.tableData.length > 0) {
            this.$nextTick(function () {
              this.toggleRowSelection(this.checkedId);
            })
          }
        });
      },
      sortChange(sortData) {
        // if (sortData.order === 'descending') {
        //   this.$set(this.searchParam, 'sort', sortData.prop);
        //   this.$set(this.searchParam, 'order', 'desc');
        // } else {
        //   this.$set(this.searchParam, 'sort', sortData.prop);
        //   this.$set(this.searchParam, 'order', 'asc');
        // }
        // this.pageNo = 1;
        // this.searchPost();
      },
      editParam(formParam) { //编辑查询用参数
        this.searchParam = {};
        for (let key in formParam) {
          if (typeof (formParam[key]) === 'string' && formParam[key].trim() !== '') {
            this.searchParam[key] = formParam[key];
          }
        }
      },
      pageChange(index) { //翻页
        this.pageNo = index;
        this.searchPost();
      },
      sizeChange(size) { //每页显示行数变更
        this.pageSize = size;
        this.refreshTable();
      },
      handleSelectionChange(array) {
        this.multipleSelection = array;
        // 传递给父组件选中行记录
        this.$emit('checkedData', this.multipleSelection);
      },
      getCheckedIdArray() {
        let idArray = this.multipleSelection.map(item => {
          return item.id;
        });
        return idArray;
      },
      getIdArray(){
        let idArray = this.tableData.map(item => {
          return item.id;
        });
        return idArray;
      },
      deleteSelect() {
        this.$confirm('此操作将永久删除, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          let array = this.multipleSelection.map((item) => {
            return item.id;
          });
          if (array.length == 0) {
            this.$message({
              type: 'warning',
              message: '请选择有效数据再删除!'
            });
          } else {
            this.axios.post(this.config.crudMapping.delete.url, array).then((response) => {
              this.$message({
                type: 'success',
                message: '删除成功!'
              });
              this.refreshTable();
            });
          }
        }).catch(() => {
          this.$message({
            type: 'info',
            message: '已取消删除'
          });
        });
      },
      publishSelect() {
        this.$confirm('确定执行此操作?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          let array = this.multipleSelection.map((item) => {
            return item.id;
          });
          this.axios.post(this.config.crudMapping.publish.url, array).then((response) => {
            this.$message({
              type: 'success',
              message: '发布成功!'
            });
            this.refreshTable();
          });
        }).catch(() => {
          this.$message({
            type: 'info',
            message: '取消发布'
          });
        });
      },
      dbClickAction(row, event) {
        this.$emit('db-row-click', row);
      },
      clearSelection() {
        this.$refs.commonTable.clearSelection();
      },
      toggleRowSelection(id) {
        if (this.tableData != null && this.tableData.length > 0) {
          this.tableData.forEach(item => {
            if (item.id == id) {
              this.$refs.commonTable.toggleRowSelection(item, true);
            }
          });
        } else {
          this.checkedId = id;
          this.searchPost();
        }
      }
    },
    components: {
      TableCell,
      SelectTree
    },
    created() {
      if (this.config && this.config.prefixCls) {
        this.prefixCls = this.config.prefixCls;
      }
      if (this.searchForm && this.searchForm != null) {
        this.searchInit();
      }
      if (!this.config.crudMapping.query) {
        return;
      }
      this.search();
    }
  }

</script>
<style scoped>
  .grid-all {
    margin: 16px;
  }

  .grid-frame {
    padding: 16px;
    border: 1px solid #DCDFE6;
    margin-bottom: 16px;
  }

  .grid-frame .grid-title {
    font-size: 16px;
    font-weight: bold;
    color: #606266;
    padding-bottom: 16px;
    border-bottom: 1px solid #E4E7ED;
    box-sizing: border-box;
    -moz-box-sizing: border-box;
    /* Firefox */
    -webkit-box-sizing: border-box;
    /* Safari */
  }

  .grid-frame .grid-title span {
    width: 300px;
    display: inline-block;
    box-sizing: border-box;
    -moz-box-sizing: border-box;
    /* Firefox */
    -webkit-box-sizing: border-box;
    /* Safari */
  }

  .grid-frame .grid-title.table-title {
    border-bottom: none;
  }

  .grid-frame .grid-title.table-title .grid-table-action {
    width: calc(100% - 305px);
    display: inline-flex;
    justify-content: flex-end;
    box-sizing: border-box;
    -moz-box-sizing: border-box;
    /* Firefox */
    -webkit-box-sizing: border-box;
    /* Safari */
  }

  .grid-table-tip {
    padding-bottom: 10px;
    width: calc(100%);
    display: inline-flex;
    justify-content: flex-end;
    box-sizing: border-box;
    -moz-box-sizing: border-box;
    /* Firefox */
    -webkit-box-sizing: border-box;
    /* Safari */
  }

  .grid-frame .grid-simple-search .grid-search-item {
    margin-top: 16px;
    margin-right: 16px;
  }

  .grid-frame .grid-page {
    margin-top: 16px;
  }

  .select-frame {
    margin-bottom: 8px;
  }

  .select-frame .select-page {
    margin-top: 8px;
  }

  .select-frame .select-title {
    font-size: 16px;
    font-weight: bold;
    color: #606266;
    padding-bottom: 2px;
    border-bottom: 1px solid #E4E7ED;
    box-sizing: border-box;
    -moz-box-sizing: border-box;
    /* Firefox */
    -webkit-box-sizing: border-box;
    /* Safari */
  }

  .select-form-inline>.clearfix{
    clear: none;
    display: inline-block;
  }

  .select-search-item{
    margin: 0;
    padding:0;
  }

  .select-title-top{
    display: none;
  }
  /*.fade-enter-active, .fade-leave-active {*/

  /*transition: opacity .8s*/

  /*}*/

  /*.fade-enter, .fade-leave-to !* .fade-leave-active in below version 2.1.8 *! {*/

  /*opacity: 0;*/

  /*}*/

</style>
<style>
  .select-frame .select-table-header-cell {
    padding: 8px 0;
  }

  .select-frame .select-table-cell {
    padding: 8px 0;
  }

</style>
